package database

import (
	"database/sql"
	"log"
	"time"

	_ "github.com/go-sql-driver/mysql"
)

// DB 数据库对象
var DB *sql.DB

// Initialize 初始化数据库
func Initialize() {
	initDB()
	createTables()
}

func initDB() {

	var err error

	// 设置数据库连接信息
	/*config := mysql.Config{
		User:                 "root",
		Passwd:               "root",
		Addr:                 "127.0.0.1:3306",
		Net:                  "tcp",
		DBName:               "share_grpc_demo",
		AllowNativePasswords: true,
	}

	// 准备数据库连接池
	DB, err = sql.Open("mysql", config.FormatDSN())*/
	DB, err = sql.Open("mysql", "root:root@tcp(mysql:3306)/share_grpc_demo")
	log.Println(err)

	// 设置最大连接数
	DB.SetMaxOpenConns(100)
	// 设置最大空闲连接数
	DB.SetMaxIdleConns(25)
	// 设置每个链接的过期时间
	DB.SetConnMaxLifetime(5 * time.Minute)

	// 尝试连接，失败会报错
	err = DB.Ping()
	log.Println(err)
}

func createTables() {
	createArticlesSQL := `CREATE TABLE IF NOT EXISTS users(
    id bigint(20) PRIMARY KEY AUTO_INCREMENT NOT NULL,
    username varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
    password varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
    email varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL
); `

	_, err := DB.Exec(createArticlesSQL)
	log.Println(err)
}

func SaveUserToDB(username string, password string, email string) (int64, error) {
	// 变量初始化
	var (
		id   int64
		err  error
		rs   sql.Result
		stmt *sql.Stmt
	)

	// 1. 获取一个 prepare 声明语句
	stmt, err = DB.Prepare("INSERT INTO users (username, password,email) VALUES(?,?,?)")
	// 例行的错误检测
	if err != nil {
		return 0, err
	}

	// 2. 在此函数运行结束后关闭此语句，防止占用 SQL 连接
	defer stmt.Close()

	// 3. 执行请求，传参进入绑定的内容
	rs, err = stmt.Exec(username, password, email)
	if err != nil {
		return 0, err
	}

	// 4. 插入成功的话，会返回自增 ID
	if id, err = rs.LastInsertId(); id > 0 {
		return id, nil
	}

	return 0, err
}

// User 对应一个用户
type User struct {
	Username, Password, Email string
	ID                        int64
}

func GetUserInfo(username, password string) (User, error) {
	info := User{}
	query := "SELECT * FROM users WHERE username = ? && password = ?"
	err := DB.QueryRow(query, username, password).Scan(&info.ID, &info.Username, &info.Password)

	if err != nil {
		return User{ID: 0}, nil
	}

	// 3. 如果出现错误
	return info, nil
}
